import box/{logger,condit,tools}

# 创建一个列表单选菜单
# 用法:
#   --title=[String]    标题
#   --tip=[String]      底部提示
#   --print-choose      显示当前选中的序号
#   --print-number      显示序号
#   --retract           选择或退出后回收菜单界面
#   --beep              启用终端响铃
Get-List-Ui(){
  [ -z "$1" ] && return 0
  trap 'printf "\e[?25h"' 2
  printf "\e[?25l"
  local __print_line=1
  local __args=()

  for i in {1..9};do
    eval "local SHIFT_${i^}=0"
  done

  function __local_arg_bis_exit { ((${!1}==0))||Err "重复的选项 $2";let "$1"++;}
  local ARGS_ERR="$arg0: 参数解析错误..."

  for arg in "$@";do
    case "$arg" in
    --title*|-t*)
      __local_arg_bis_exit SHIFT_1 "$arg"
      ARG_ERR="未指定标题" \
      ARG_OPTS="t,title" \
      ARG_KEY="__arg_title" \
      Get-Option "$@"
      shift $__return__
      ;;
    --tip*|-m*)
      __local_arg_bis_exit SHIFT_2 "$arg"
      ARG_ERR="未指定提示" \
      ARG_OPTS="m,tip" \
      ARG_KEY="__arg_tip" \
      Get-Option "$@"
      shift $__return__
      ;;
    --retract)
      __local_arg_bis_exit SHIFT_3 "$arg"
      local __retract=true
      shift
      ;;
    --beep)
      __local_arg_bis_exit SHIFT_4 "$arg"
      local __is_beep=true
      shift
      ;;
    --print-choose)
      __local_arg_bis_exit SHIFT_5 "$arg"
      local __display_choose=true
      shift
      ;;
    --print-number)
      __local_arg_bis_exit SHIFT_6 "$arg"
      local __print_line_number=true
      shift
      ;;
    -*)
      Err "$(sed 's#=.*$##;s#--##' <<< $arg): 未知的选项"
      [[ ! -z $__is_beep ]] && printf "\a\e[?25h"
      return 0
      ;;
    *)
      local __args+=("$arg")
      shift
    esac
  done
  local __args_number=${#__args[@]}
  local __args_renum=$__args_number
  local __title=${__arg_title##*=}
  local __tip=${__arg_tip##*=}

  [[ ! -z "$__is_beep" ]] && printf "\a"
  while true;do
    local __args_number=${#__args[@]}
    local __title=${__arg_title##*=}
    local __tip=${__arg_tip##*=}
    [[ ! -z "$__display_choose" ]] &&
    let __args_number++
    [[ ! -z "$__arg_tip" ]] &&
    local __args_number=$[__args_number+2]
    printf "\n" && let __args_number++
    [ ! -z "$__title" ] && printf "\r${__title}\n\n" && __args_number=$[__args_number+2]
    local __choose_line=1
    for ((n=1;n<$[__args_renum+1];n++));do
      local __line=${__args[n-1]}
      [[ $__print_line == $n ]]&&local __line_head="\e[7m"||local __line_head=''
      [[ ! $n == $__args_renum ]]&&local __line_end="\n"||local __line_end=""
      [[ ! -z $__print_line_number ]]&&local __line_number="$(printf "%2d" $n). "||local __line_number=""
      printf "\r\e[0m $__line_number$__line_head${__line}\e[0m$__line_end"
      let __choose_line++
    done
    [[ ! -z $__display_choose ]] &&
    printf "\n选择: %2d" $__print_line
    local __tip="${__tip:-使用向上/向下箭头进行选择, 按回车确认.}"
    [[ ! -z $__arg_tip ]] &&
    printf "\n\n\e[38;2;180;180;180m${__tip}\e[0m"
    local __read_key=$(Read-Keyboard)  
    case $__read_key in
      up|-)[[ $__print_line == 1 ]] && __print_line=$__args_renum || let __print_line--;;
      down|+)[[ $__print_line == $__args_renum ]] && __print_line=1 || let __print_line++;;
      home)__print_line=1;;
      end)__print_line=$__args_renum;;
      q|esc)
          [[ ! -z $__is_beep ]] && printf "\a"
          if [[ ! -z $__retract ]];then
            printf "\e[$[__args_number-1]A"
            for ((i=1;i<=__args_number;i++));do
              printf "\r\e[K\n"
            done
            printf "\e[${__args_number}A"
          fi
          printf "\e[?25h"
          __return__=0
          return
      ;;
      *)if [[ $__read_key =~ ^[0-9]$ ]];then
          [[
            $__read_key -gt 0 &&
            $__read_key -lt $__choose_line
          ]] && __print_line=$__read_key
        elif [[ $__read_key == enter ]];then
          [[ ! -z $__is_beep ]] && printf "\a"
          if [[ ! -z $__retract ]];then
            printf "\e[$[__args_number-1]A"
            for ((i=1;i<=__args_number;i++));do
              printf "\r\e[K\n"
            done
            printf "\e[$[__args_number+1]A"
          fi
            printf "\n\e[?25h"
            __return__=$__print_line
            return
        fi
    esac
    [[ ! -z $__is_beep ]] && printf "\a"
    printf "\e[$[__args_number-1]A"
  done
}

# 创建一个询问菜单
# 用法:
# Get-Ask-Ui [询问内容] [Yes|No]
# 由第二个参数控制默认选择项
Get-Ask-Ui(){
  : ${__TTB_GET_ASK_RETRACT:=true}
  # @Value __return__
  # yes   真
  # no    假
  # exit  退出
  function __print_choose_yes(){ printf "\r╰ \e[%dm$__iron_select\e[0m Yes / $__grey$__iron_not_select No\e[0m" "$1";}
  function __print_choose_no(){ printf "\r╰ $__grey$__iron_not_select Yes\e[0m / \e[%dm$__iron_select\e[0m No" "$1";}
  function __reset_1(){ printf "\e[?25h\n";for i in {1..2};do printf "\e[1A\r\e[K";done;}
  function __reset_2(){ printf "\e[?25h";In-Value __yes && __print_choose_yes 32 || __print_choose_no 32;echo;}
  function __reset(){ In-Value __TTB_GET_ASK_RETRACT && __reset_1 || __reset_2;}
  [ -z "$1" ] && return 0
  local __default=${2:-yes}
        __default=${__default,,}
  local __iron_not_select='○'
  local __iron_select='●'
  local __grey="\e[38;2;180;180;180m"
  
  # 前置准备
  case $__default in
    yes)
      local __default_print="[Y/n]"
      local __yes=true
    ;;
    no)
      local __default_print="[y/N]"
      local __yes=false
  esac
  
  # 准备拼接界面
  printf "\e[?25l"
  echo -e "╭ $1 $__default_print"
  while true;do
    if In-Value __yes;then
      __print_choose_yes 34
    else
      __print_choose_no 34
    fi
    local __read_key=$(Read-Keyboard)
    case $__read_key in
      enter)__reset;In-Value __yes && __return__=yes || __return__=no;return;;
      esc)__reset;__return__=exit;return;;
      left|right)In-Value __yes && __yes=false || __yes=true;;
    esac
  done
}